// locutor
// (c) 2008-2009, Normen Müller, normen.mueller@gmail.com  
// $Id: Parser.scala 2456 2009-10-04 08:54:35Z nmueller $
package locutor.model.parsing.dm

import java.io.File

import scala.util.parsing.combinator._
import scala.util.parsing.combinator.syntactical._

import scaup.Views._

/** 
 * @author <a href="mailto:normen.mueller@googlemail.com">Normen M&#xFC;ller</a>
 * @version 0.0.2 */
private [dm] class Parser extends StdTokenParsers with ImplicitConversions {
  /* Fill in abstract defs*/
  type Tokens = Lexer
  val lexical: Tokens = new Lexer
  
  /* Configure lexical parsing */                                 
  lexical.reserved ++= List("model", "for", "at", "using")
  lexical.delimiters ++= List("{", "}", "[", "]", "-:", ":", "=", ";", ",", "->")
  
  /* Define the grammar */
  def dm    = "model" ~ ident ~ "for" ~ doc ~ "at" ~ rev ~ "{" ~ stmts ~ "}"
  def stmts = gms ~ dg
  def gms   = "using" ~ string ~ opt(";")
  def dg    = (ident ~ ":" ~ ident ~ (attrs | "-:" ~ ident ~ opt(attrs) ~ "->" ~ ident) ~ opt(";"))*
  def attrs = "[" ~ ((attrp ~ opt(","))*) ~ "]"
  def attrp = key ~ "=" ~ value
  
  def doc   = string ^^ {case d if d.toFile exists => d.toFile}
  def rev   = numeric
  def key   = string | ident | numeric
  def value = string | ident | numeric
  
  def string   = accept("string",  {case lexical.StringLit(n) => n})
  def numeric  = accept("numeric", {case lexical.NumericLit(n) => n.toInt})
}


/*
def gm       = (("using" ~> string) <~ opt(";") ^^ {
    case gs => (Set.empty[File] /: gs.split(",\\s*"))(_ + _.toFile)
  }) ^? (
    {case gs if gs forall (_ exists) => gs},
    {case gs => "Graph models may not be null."}
  )
*/
